import java.io.*;

public class Client {
    private BufferedReader userInput = new BufferedReader(new InputStreamReader(System.in));
    private String UserName = "guest";
    private String ServerIP = "127.0.0.1";
    private int ServerPort = 8189;
    private int MyTimeout = 10000;
    private Connection conn = null;

    public static void main(String args[]) {
        Client cli = new Client();
        cli.runClient();
    }

    public void runClient() {
        String user_input;
        Pack[] received;
        long processReturn;
        int i;

        System.out.println("Please enter your user name:");
        this.UserName = getInput();

        System.out.println("Please enter the server IP address:");
        this.ServerIP = getInput();

        this.conn = new Connection(ServerIP, ServerPort, MyTimeout);

        if(!this.conn.isConnected()) {
            System.err.println("Error connecting to server please consult your log file.");
            return;
        }

        while(this.conn.isConnected()) {
            received = this.conn.recieveData();
            if(received != null) {
                for(i = 0; i < received.length; i++) {
                    processPack(received[i]);
                }
            }
            
            if(inputAvailable() && this.conn.isConnected()) {
                user_input = getInput();
                if(user_input.equals("quit")) {
                    System.out.println("User ending application, exiting...");
                    this.conn.closeConnection("Client closing application.");
                } else if(user_input.equals("?ports?")) {
                    System.out.println("-------------------");
                    System.out.println("---- Port Info ----");
                    System.out.println("Local Port: " + this.conn.myPort());
                    System.out.println("Remote Port: " + this.conn.theirPort());
                    System.out.println("-------------------");
                } else if(user_input.equals("?ips?")) {
                    System.out.println("-----------------");
                    System.out.println("---- IP Info ----");
                    System.out.println("Local IP: " + this.conn.myIP());
                    System.out.println("Remote IP: " + this.conn.theirIP());
                    System.out.println("-----------------");
                } else {
                    this.conn.sendData(new Pack(Pack.FORWARD_DATA_ID, user_input, this.conn.myIP(), this.conn.theirIP()));
                }
            }
        }
    }

    private void processPack(Pack p) {
    // Returns -2 if port change failed (ie no active connection to server)
    // Returns -1 if null parsed
    // Returns requestID if a pack parsed
        if(p != null) {
            if(p.requestID == Pack.CLOSE_CONNECTION_ID) {
                System.out.println("Close connection notification received, closing connection...");
                this.conn.closeConnection();
            }
            
            if (p.requestID == Pack.CHANGE_PORT_ID) {
                System.out.println("Received port change notification, restarting connection on port " + p.data);
                this.ServerPort = Integer.parseInt(p.data);
                this.conn.closeConnection("Port change notification received - restarting client with new port " + this.ServerPort, false);
                
                if(this.conn.initConnection(ServerIP, ServerPort, MyTimeout)) {
                    System.out.println("Successfully switched ports.");
                } else {
                    System.err.println("Port switching failed, cannot recover exiting.");
                }
            }
            
            if(p.requestID == Pack.FORWARD_DATA_ID) {
                System.out.println(p.fromAddr + " says: " + p.data);
            }
        }
    }

    private boolean inputAvailable() {
        try {
            return userInput.ready();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
        return false;
    }
    
    private String getInput() {
        String tmp = "";
        try {
            tmp = userInput.readLine();
        } catch (Exception e) {
            tmp = "";
        }
        return tmp;
    }
}
